package com.yxx.strategy.uploadStrategyImpl;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.yxx.config.properties.CosProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.qcloud.cos.region.Region;


import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;

/**
 * cos上传策略
 * @author yuxiangxun
 * @date 2025/1/27
 * @apiNote
 */
@Slf4j
@Service("cosUploadStrategyImpl")
public class CosUploadStrategyImpl extends AbstractUploadStrategyImpl{

    @Resource
    private CosProperties cosProperties;

    /**
     * 判断文件是否存在
     * @param filePath 文件路径
     * @return
     */
    @Override
    public Boolean exists(String filePath) {
        return createCOSClient().doesObjectExist(cosProperties.getBucketName(),filePath);
    }

    /**
     * 上传
     * @param path        路径
     * @param fileName    文件名
     * @param inputStream 输入流
     * @throws IOException
     */
    @Override
    public void upload(String path, String fileName, InputStream inputStream) {
        // 采用上传流类型方式进行文件上传
        COSClient cosClient = createCOSClient();
        try{
            String FileKey = path + fileName;
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 上传的流如果能够获取准确的流长度，则推荐一定填写 content-length
            // 如果确实没办法获取到，则下面这行可以省略，但同时高级接口也没办法使用分块上传了
            objectMetadata.setContentLength(inputStream.available());
            // 调用cos方法上传
           cosClient.putObject(cosProperties.getBucketName(),FileKey,inputStream,objectMetadata);
        }catch (CosServiceException e) {
            log.error("Error Message:" + e.getErrorMessage());
            log.error("Error Code:" + e.getErrorCode());
            log.error("Request ID:" + e.getRequestId());
        } catch (CosClientException e) {
            log.error("Caught an CosClientException, Error Message:" + e.getMessage());
        } catch (IOException e) {
            log.error("Caught an IOException, Error Message:" + e.getMessage());
        } finally {
            // 确认本进程不再使用 cosClient 实例之后，关闭即可
            cosClient.shutdown();
        }
    }

    /**
     * 获取文件访问url
     * @param filePath 文件路径
     * @return
     */
    @Override
    public String getFileAccessUrl(String filePath) {
        return cosProperties.getUrl() + filePath;
    }

    /**
     * 看官方文档搭建COSClient实例
     * 创建 COSClient 实例，这个实例用来后续调用请求
     * @return
     */
    private COSClient createCOSClient() {
        // 设置用户身份信息。
        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
        //String secretId = System.getenv("secretId");//用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
        //String secretKey = System.getenv("secretKey");//用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
        // 获取 secretId 和 secretKey

        // 初始化用户身份信息（secretId 和 secretKey）
        COSCredentials cred = new BasicCOSCredentials(cosProperties.getSecretId(), cosProperties.getSecretKey());

        // ClientConfig 中包含了后续请求 COS 的客户端设置：
        ClientConfig clientConfig = new ClientConfig();

        // 设置 bucket 的地域
        // COS_REGION 请参见 https://cloud.tencent.com/document/product/436/6224
        clientConfig.setRegion(new Region(cosProperties.getRegion()));

        // 以下的设置，是可选的：

        // 设置 socket 读取超时，默认 30s
        // clientConfig.setSocketTimeout(30*1000);
        // 设置建立连接超时，默认 30s
        // clientConfig.setConnectionTimeout(30*1000);

        // 如果需要的话，设置 http 代理，ip 以及 port
        // clientConfig.setHttpProxyIp("httpProxyIp");
        // clientConfig.setHttpProxyPort(80);

        // 建议设置使用 https 协议，可以有效降低网络传输质量
        // 从5.6.54 版本开始，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);

        // 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }
}
